package com.whu;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


public class MiniApplicationContext {

    /**
     * 用hashmap来存储bean实例
     */
    private Map<String,Object> beanMap = new HashMap<>();

    /**
     * 构造方法,传入Xml文件路径，解析该xml文件
     */
    public MiniApplicationContext(String xml)  {
        try{
            //创建读取配置文件的reader对象
            SAXReader reader = new SAXReader();
            //获取当前线程中的类加载器对象
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            //从class目录下获取指定的xml文件
            InputStream inputStream = classLoader.getResourceAsStream(xml);
            //使用dom4j解析xml文件
            Document document = reader.read(inputStream);
            Element root = document.getRootElement();
            //初始化bean
            setBean(root);
            dependenceInjection(root);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 初始化bean
     */
    public void setBean(Element root)throws Exception{
        //遍历xml文件中的bean实例
        for (Iterator i = root.elementIterator("bean");i.hasNext();){
            Element foo = (Element) i.next();
            //获取每个bean的属性和class
            String id = foo.attribute("id").getText();
            String cls = foo.attribute("class").getText();
            //反射获取class对象
            Class bean = Class.forName(cls);
            //创建对象
            Object obj = bean.newInstance();
            //将对象存放在beanMap中
            beanMap.put(id,obj);
        }
    }

    /**
     * 注入依赖
     */
    public void dependenceInjection(Element root) throws Exception {
        for (Iterator<?> i2 = root.elementIterator("bean");i2.hasNext();){
            Element foo = (Element) i2.next();
            String id = foo.attribute("id").getText();
            String cls = foo.attribute("class").getText();
            Class<?> bean1 = Class.forName(cls);
            //获取对应class的信息
            BeanInfo info = Introspector.getBeanInfo(bean1);
            PropertyDescriptor[] pd = info.getPropertyDescriptors();

            //遍历获取该bean的property属性
            for(Iterator<?> i3 = foo.elementIterator("property"); i3.hasNext();){
                Element foo2 = (Element) i3.next();
                //获取name、ref、value
                String name = foo2.attribute("name").getText();
                //注入引用类型
                if(foo2.attribute("ref")!=null){
                    String ref = foo2.attribute("ref").getText();
                    for (PropertyDescriptor propertyDescriptor : pd) {
                        if (propertyDescriptor.getName().equalsIgnoreCase(name)) {
                            Method method = propertyDescriptor.getWriteMethod();
                            method.invoke(beanMap.get(id), beanMap.get(ref));
                        }
                    }
                }
                //注入基本类型和String类型
                if(foo2.attribute("value")!=null){
                    String value = foo2.attribute("value").getText();
                    for (PropertyDescriptor propertyDescriptor : pd) {
                        if (propertyDescriptor.getName().equalsIgnoreCase(name)) {
                            Method method = propertyDescriptor.getWriteMethod();
                            method.invoke(beanMap.get(id), value);
                        }
                    }
                }

            }
        }
    }

    /**
     * 通过id获取bean实例
     */
    public Object getBean(String id){
        Object obj = beanMap.get(id);
        return obj;
    }
}
